package com.atguigu.juc.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author yanglin
 * @create 2024-01-25 16:21 星期四
 * description:演示ABA问题
 */
public class ABADemo {

    static AtomicInteger atomicInteger = new AtomicInteger(100);
        
    //初始版本号为1
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference(100,1);
    
    public static void main(String[] args) {
              new Thread(() -> {
                  int stamp = atomicStampedReference.getStamp();
                  System.out.println(Thread.currentThread().getName() + "\t 首次版本号为：" + stamp);
                  
                  //保证t4拿到的版本号一样
                  try {
                      TimeUnit.MILLISECONDS.sleep(500);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  
                  //发生一次ABA问题
                  boolean b = atomicStampedReference.compareAndSet(100, 101, stamp, ++stamp);
                  System.out.println("t3第一次修改是否成功：" + b + " stamp = " + stamp);
                  boolean b1 = atomicStampedReference.compareAndSet(101, 100, stamp, ++stamp);
                  System.out.println("t3第二次修改是否成功：" + b1 + " stamp = " + stamp);
              },"t3").start();
              
              new Thread(() -> {

                  int stamp = atomicStampedReference.getStamp();
                  System.out.println(Thread.currentThread().getName() + "\t 首次版本号为：" + stamp);

                  //暂停1s，确保ABA问题出现
                  try {
                      TimeUnit.SECONDS.sleep(1);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  //尝试修改
                  boolean b = atomicStampedReference.compareAndSet(100, 2022, stamp, ++stamp);
                  System.out.println("t4第一次修改是否成功：" + b + " stamp = " + atomicStampedReference.getStamp());
              },"t4").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(atomicStampedReference.getReference());
    }


    /**
     * 演示ABA问题
     */
    public static void ABAHappen() {
        new Thread(() -> {
            boolean b = atomicInteger.compareAndSet(100, 101);
            System.out.println("是否修改成功：" + b);
            //暂停10毫秒
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //改回原来的
            boolean b1 = atomicInteger.compareAndSet(101, 100);
            System.out.println("是否修改成功：" + b1);
        },"t1").start();

        new Thread(() -> {
            //确保在线t1上发生了ABA问题
            try {
                TimeUnit.MILLISECONDS.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean b = atomicInteger.compareAndSet(100, 2022);
            System.out.println("是否修改成功：" + b);
        },"t2").start();
    }

}
